package com.zilue.payment.gateway.manage;

import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.fastjson.JSON;
import com.zilue.balance.domain.BaseOrderInfo;
import com.zilue.balance.returnresult.Result;
import com.zilue.payment.gateway.common.RefundStatusEnums;
import com.zilue.payment.gateway.domain.CorpDO;
import com.zilue.payment.gateway.domain.PayOrderDO;
import com.zilue.payment.gateway.domain.RefundLogDO;
import com.zilue.payment.gateway.exception.BizManagerException;
import com.zilue.payment.gateway.method.remote.BalancePayRemote;
import com.zilue.payment.gateway.paramter.order.RefundParameter;
import com.zilue.payment.gateway.reurndata.enums.BusinessStatusEnum;
import com.zilue.payment.gateway.reurndata.enums.RequestStatusEnum;
import com.zilue.payment.gateway.reurndata.order.RefundReturn;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

/**
 * Created by zilue on 2017/3/9.
 */
@Service
public class OrderRefundManager extends BaseManager {
    private Logger logger = Logger.getLogger(OrderRefundManager.class);
    @Autowired
    private BalancePayRemote balancePayRemote;

    @Transactional
    public RefundReturn refund(CorpDO corpDO, RefundParameter refundParameter) {
        RefundReturn refundReturn = new RefundReturn(RequestStatusEnum.RequestSuccess);
        //查询订单
        PayOrderDO payOrder = queryByOrderNoOutTradeNo(refundParameter.getOrder_no(), refundParameter.getOut_trade_no(), refundParameter.getOut_pay_no(), corpDO.getParentCorpId(), corpDO.getCorpId());
        if (payOrder == null) {
            refundReturn.setBusinessStatus(BusinessStatusEnum.OrderNotExist);
            return refundReturn;
        }

        //判断是全退还是部分退
        if (StringUtils.isEmpty(refundParameter.getOut_refund_no()) && refundParameter.getFee() == null) {
            logger.info("全部退费请求：" + JSON.toJSONString(refundParameter));
            refundParameter.setOut_refund_no(payOrder.getOutTradeNo());
            refundParameter.setFee(payOrder.getTotalAmount());
        }
        if (refundParameter.getFee() == null || refundParameter.getFee().intValue() == 0) {
            refundReturn.setBusinessStatus(BusinessStatusEnum.OrderFeeIllegal);
            return refundReturn;
        }

        //1.检查是否有退费记录
        RefundLogDO refundLogDO = queryRefundLog(payOrder.getOutTradeNo(), refundParameter.getOut_refund_no());
        if (refundLogDO != null) {
            if (RefundStatusEnums.REFUND_SUCCUSS.getCode().equals(refundLogDO.getStatus())) {
                if (refundLogDO.getFee().equals(refundParameter.getFee()) && refundLogDO.getOutRefundNo().equals(refundParameter.getOut_refund_no())) {
                    refundReturn.setBusinessStatus(BusinessStatusEnum.RefundOrderSuccess);
                    refundReturn.setOut_trade_no(refundLogDO.getOutTradeNo());
                    refundReturn.setOut_pay_no(payOrder.getOutPayNo());
                    refundReturn.setOut_refund_no(refundLogDO.getOutRefundNo());
                    refundReturn.setOrder_no(payOrder.getOrderNo());
                    refundReturn.setFee(refundLogDO.getFee());
                    return refundReturn;
                } else {
                    refundReturn.setBusinessStatus(BusinessStatusEnum.OrderOutRefundNoIllegal);
                    return refundReturn;
                }
            } else if (!RefundStatusEnums.PROCESSING.getCode().equals(refundLogDO.getStatus())) {
                refundReturn.setBusinessStatus(BusinessStatusEnum.Busyness);
                return refundReturn;
            }
        }

        //2.检查原订单状态
        if (PayOrderDO.STATUS_WAIT_FOR_PAY.equals(payOrder.getStatus())) {
            refundReturn.setBusinessStatus(BusinessStatusEnum.OrderNotPay);
            return refundReturn;
        } else if (PayOrderDO.STATUS_CLOSED.equals(payOrder.getStatus())) {
            refundReturn.setBusinessStatus(BusinessStatusEnum.OrderClosed);
            return refundReturn;
        } else if (PayOrderDO.STATUS_REFUND.equals(payOrder.getStatus())) {
            refundReturn.setBusinessStatus(BusinessStatusEnum.OrderRefunded);
            return refundReturn;
        } else if (PayOrderDO.STATUS_CANCLE.equals(payOrder.getStatus())) {
            refundReturn.setBusinessStatus(BusinessStatusEnum.OrderCancled);
            return refundReturn;
        } else if (!PayOrderDO.STATUS_SUCCESS.equals(payOrder.getStatus())) {//其他状态
            refundReturn.setBusinessStatus(BusinessStatusEnum.OrderStatusIllegal);
            return refundReturn;
        }

        //3.检查退费金额
        if (payOrder.getRefundFee().equals(payOrder.getTotalAmount())) {
            refundReturn.setBusinessStatus(BusinessStatusEnum.OrderRefunded);
            updatePayOrderStatus(payOrder.getId(), payOrder.getStatus(), PayOrderDO.STATUS_REFUND);
            return refundReturn;
        }
        if (payOrder.getRefundFee() + refundParameter.getFee() > payOrder.getTotalAmount()) {
            refundReturn.setBusinessStatus(BusinessStatusEnum.RefundFeeIllegal);
            refundReturn.appendSub_msg("，订单总金额为"+new BigDecimal(payOrder.getTotalAmount()).divide(BigDecimal.valueOf(100L))+"元，剩余可退金额为"+new BigDecimal(payOrder.getTotalAmount()-payOrder.getRefundFee()).divide(BigDecimal.valueOf(100L))+"元");
            return refundReturn;
        }

        //4.记录退费log
        if (refundLogDO == null) {
            refundLogDO = insertRefundLog(payOrder, refundParameter);
            if (refundLogDO == null) {
                refundReturn.setBusinessStatus(BusinessStatusEnum.RefundOrderSuccess);
                return refundReturn;
            }
        }

        //5.更新支付订单的信息
        boolean updateOK = updatePayOrderRefundFee(payOrder.getId(), payOrder.getRefundFee(), refundParameter.getFee());
        if (!updateOK) {
            throw new BizManagerException(BusinessStatusEnum.RefundFeeChanged);
        }

        //6.调用虚拟结算退费
        logger.info("调用虚拟结算扣费！" + JSON.toJSONString(refundParameter));
        Result<BaseOrderInfo> refund;
        try {
            refund = balancePayRemote.refund(payOrder.getOutPayNo(), payOrder.getCorpId(), refundParameter.getFee(), 1, refundParameter.getTerminal_id(), refundParameter.getOperator_id());
        } catch (RpcException e) {
            logger.error("严重！！调用虚拟结算退费异常,Dubbo异常！！！(交易金额回滚) 退费请求参数：" + JSON.toJSONString(refundParameter) + " 原交易订单：" + JSON.toJSONString(payOrder), e);
            throw new BizManagerException(BusinessStatusEnum.Busyness);
        } catch (Exception e) {
            logger.error("严重！！调用虚拟结算退费异常！！！(交易金额回滚)  退费请求参数：" + JSON.toJSONString(refundParameter) + " 原交易订单：" + JSON.toJSONString(payOrder), e);
            throw new BizManagerException(BusinessStatusEnum.Busyness);
        }
        boolean refundOK = refund.isSuccess();
        if (!refundOK) {
            throw new BizManagerException(BusinessStatusEnum.RefundOrderFailed, refund.getMsg());
        }
        Boolean ok= updateRefundLogStatus(refundLogDO.getOutTradeNo(),refundLogDO.getOutRefundNo(), RefundStatusEnums.PROCESSING.getCode(), RefundStatusEnums.REFUND_SUCCUSS.getCode());

        if (payOrder.getTotalAmount().equals(payOrder.getRefundFee() + refundParameter.getFee()))//全部退完更新支付订单状态
            updatePayOrderStatus(payOrder.getId(), payOrder.getStatus(), PayOrderDO.STATUS_REFUND);
        //7.封装业务返回对象
        refundReturn.setBusinessStatus(BusinessStatusEnum.RefundOrderSuccess);
        refundReturn.setOut_trade_no(refundLogDO.getOutTradeNo());
        refundReturn.setOut_pay_no(payOrder.getOutPayNo());
        refundReturn.setOut_refund_no(refundLogDO.getOutRefundNo());
        refundReturn.setOrder_no(payOrder.getOrderNo());
        refundReturn.setFee(refundLogDO.getFee());
        return refundReturn;

    }


}
